/*
	Copyright (c) 2010 <copyright holders>
	This source code is licensed under The MIT License,
	see the file LICENSE for details.
	*/

#ifndef UNITINTERPOLATOR_HPP
#define UNITINTERPOLATOR_HPP

#include "EntityInterpolator.hpp"
#include "Unit.hpp"
#include "SmoothFloat.hpp"
#include <vector>

namespace spelprog2 {
namespace presentation {

class UnitInterpolator;

class UnitState
{
public:
    UnitState();

    float getWeight(){return weight.get();}
    float getNormalizedWeight(UnitInterpolator *ui);
    
    void setBlendOutTime(float time){blendOutTime = time;}
    float getBlendOutTime(float time){return blendOutTime;}
    
    void setBlendInTime(float time){blendInTime = time;}
    float getBlendInTime(float time){return blendInTime;}
    
    void enable(UnitInterpolator *ui){if(active)return; init(ui); active = true; weight.set(1.0f, blendInTime); disabled = false; update(0.0f, ui);}
    void instantEnable(UnitInterpolator *ui){enable(ui); weight = 1.0;}
    
    void disable(){active = false; weight.set(0.0f, blendOutTime); age = 0;}
    void instantDisable(){disable(); weight = 0;}
    void handleAnimation(Ogre::String animation){animations.push_back(animation);}
    
    bool getIsActive(){return active;}
    
    double getAge(){return age;}
    
    void update(float time, UnitInterpolator *ui);
    virtual void stateUpdate(UnitInterpolator *ui, sim::Unit::ConstPointer unit){};

private:
    bool active;
    bool disabled;
    double age;
    std::vector<Ogre::String> animations;
    
protected:
    SmoothFloat weight;
    float blendOutTime;
    float blendInTime;
    
    virtual void goUpdate(float time, UnitInterpolator *ui){};
    virtual void init(UnitInterpolator *ui) = 0;
    virtual void end(UnitInterpolator *ui) = 0;
};

class MotionState: public UnitState
{
public:
    MotionState();
    void stateUpdate(UnitInterpolator *ui, sim::Unit::ConstPointer unit);
    
protected:
    SmoothFloat speed;

    void goUpdate(float time, UnitInterpolator *ui);
    void init(UnitInterpolator *ui);
    void end(UnitInterpolator *ui);
};

class FightState: public UnitState
{
public:
    FightState();
    void stateUpdate(UnitInterpolator *ui, sim::Unit::ConstPointer unit);
    
protected:
    float startTime;
    
    void goUpdate(float time, UnitInterpolator *ui);
    void init(UnitInterpolator *ui);
    void end(UnitInterpolator *ui);
};

class DeathState: public UnitState
{
public:
    DeathState();
    void stateUpdate(UnitInterpolator *ui, sim::Unit::ConstPointer unit);
    
protected:
    void goUpdate(float time, UnitInterpolator *ui);
    void init(UnitInterpolator *ui);
    void end(UnitInterpolator *ui);
};

class UnitInterpolator : public EntityInterpolator {
public:
    UnitInterpolator(sim::Unit::ConstPointer unit, sim::Int playerId, sim::Int squadId,
    const LandscapeSpatials & spatials, Ogre::SceneManager & sceneMan);

    void onUnitUpdate(sim::Unit::ConstPointer unit);
    virtual void gfxUpdate(float deltaTime);
    
    float stateWeightSum();
    float getSpeed(){return speed;}

protected:
    float speed;
    SmoothFloat rotation;
    MotionState stateMotion;
    FightState stateFighting;
    DeathState stateDeath;
};

}; //presentation
}; //spelprog2

#endif //UNITINTERPOLATOR_HPP
